package com.xuelang.component;

import cn.hutool.crypto.digest.MD5;
import com.xuelang.pipeline.artifact.client.common.constant.ArtifactConstant;
import com.xuelang.pipeline.artifact.client.common.result.PageRecord;
import com.xuelang.pipeline.artifact.client.common.util.CryptoUtils;
import com.xuelang.pipeline.artifact.client.common.validator.KeyInfoEncrypted;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

import java.lang.reflect.Field;
import java.util.Collection;
import java.util.Optional;

@Aspect
@Component
@Order(1)
@Slf4j
public class EncryptionAspect {

    /**
     * 对返回结果进行加密
     *
     * @param joinPoint
     * @param result
     */
    @AfterReturning(pointcut = "execution(* com.xuelang.pipeline.artifact.app..*.*(..))", returning = "result")
    public void encryptField(JoinPoint joinPoint, Object result) {
        if (result instanceof Collection) {
            Optional.of(result).ifPresent(ret -> {
                ((Collection<?>) ret).forEach(this::encryptFields);
            });
        } else if (result instanceof PageRecord) {
            PageRecord<?> pageResult = ((PageRecord<?>) result);
            Optional.of(pageResult).flatMap(record -> Optional.ofNullable(record.getRecords())).ifPresent(records -> {
                records.forEach(this::encryptFields);
            });
        } else {
            encryptFields(result);
        }
    }

    /**
     * md5加密
     */
    private static final MD5 MD5_INSTANCE = MD5.create();

    /**
     * 加密字段
     *
     * @param object
     */
    private void encryptFields(Object object) {
        if (object == null) {
            return;
        }
        try {
            Field[] fields = object.getClass().getDeclaredFields();
            for (Field field : fields) {
                if (field.isAnnotationPresent(KeyInfoEncrypted.class)) {
                    field.setAccessible(true);
                    Object value = field.get(object);
                    if (value != null) {
                        try {
                            //String valueString = (String) value;
                            //field.set(object, MD5_INSTANCE.digestHex(valueString));
                            //field.set(object, "***-----***");
                            String valueString = (String) value;
                            field.set(object, CryptoUtils.encryptBySRSA(ArtifactConstant.PUBLIC_KEY_S, valueString));
                        } catch (Exception e) {
                            log.error("关键信息加密失败：{}", e.getMessage());
                            field.set(object, "[--------]");
                        }
                    }
                }
            }
        } catch (IllegalAccessException e) {
            throw new RuntimeException(e);
        }
    }
}